package cc.rengu.redp.flowable.bizmodel.metadata;

import cc.rengu.redp.flowable.bizmodel.calculate.FieldAlgHelper;
import cc.rengu.redp.flowable.bizmodel.calculate.FieldAlgorithm;
import cc.rengu.redp.flowable.bizmodel.convert.BizDataConverter;
import cc.rengu.redp.flowable.bizmodel.convert.BizKeyGenerator;
import cc.rengu.redp.flowable.bizmodel.convert.Converter;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgAlg;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgField;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizCfgModel;
import cc.rengu.redp.flowable.bizmodel.db.domain.BizData;
import cc.rengu.redp.flowable.bizmodel.domain.BizFieldsForCal;
import cc.rengu.redp.flowable.bizmodel.web.service.BizCfgFieldService;
import cc.rengu.redp.flowable.bizmodel.web.service.BizDataService;
import cc.rengu.redp.system.domain.User;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class BizDataModelHandler implements ModelHandler {

    @Autowired
    DictHandler dictHandler;
    @Autowired
    IndexHandler indexHandler;
    @Autowired
    BizDataService bizDataService;
    @Autowired
    BizCfgFieldService bizCfgFieldService;

    @Override
    public void create(JSONObject srcJsonObj, BizCfgModel bizCfgModel) {

        //把主键规则相同的字段归纳在一个事务中处理，生成一条业务数据
        //<主键算法表达-键值生成器，<字段列表, 字段值计算参数>>
        Map<String, Map<String, BizFieldsForCal>> createBizDataFieldList = new HashMap<>();
        //<主键算法表达-指定字段组合，<字段列表, 字段值计算参数>>
        Map<String, Map<String, BizFieldsForCal>> updateBizDataFieldList = new HashMap<>();
        //获取键值字段名称
        LambdaQueryWrapper<BizCfgField> keyFieldCfgLqw = new LambdaQueryWrapper<>();
        keyFieldCfgLqw.eq(BizCfgField::getModelId, bizCfgModel.getModelId()).eq(BizCfgField::getIsPriKey, true);
        List<BizCfgField> bizCfgFields = bizCfgFieldService.list(keyFieldCfgLqw);
        String keyFieldName = null;
        if (bizCfgFields.size() == 1) {
            keyFieldName = bizCfgFields.get(0).getFieldName();
        }

        for (BizCfgField bizCfgField : bizCfgModel.getFieldData()) {
            //键值字段（冗余处理，因为键值字段没有字段算法，所以正常时不存在）
            if (bizCfgField.getIsPriKey() == true) {
                continue;
            }

            List<BizCfgAlg> bizCfgAlgs = bizCfgField.getAlgData();
            bizCfgAlgs.forEach(bizCfgAlg -> {
                if (bizCfgAlg.getPriKeyAlgType().equals(FieldAlgHelper.AlgType.UniqKeyGenerator)) {
                    if (StringUtils.isBlank(bizCfgAlg.getPriKeyAlgDesc())) {
                        log.error("AlgId:[{}], 键值描述字段不可为空", bizCfgAlg.getAlgId());
                        return;
                    }

                    //系统生成
                    Map<String, BizFieldsForCal> oneBizDataField = createBizDataFieldList.get(bizCfgAlg.getPriKeyAlgDesc());
                    if (oneBizDataField == null) {
                        oneBizDataField = new HashMap<>();
                        createBizDataFieldList.put(bizCfgAlg.getPriKeyAlgDesc(), oneBizDataField);
                    }
                    BizFieldsForCal bizFieldsForCal = new BizFieldsForCal();
                    bizFieldsForCal.setFieldName(bizCfgField.getFieldName());
                    bizFieldsForCal.setFatherFieldName(bizCfgField.getFatherFieldName());
                    FieldAlgorithm fieldAlgorithm = FieldAlgHelper.get(bizCfgAlg.getAlgType(), bizCfgAlg.getAlgDesc());
                    bizFieldsForCal.setFieldAlgorithm(fieldAlgorithm);
                    oneBizDataField.put(bizCfgField.getFieldName(), bizFieldsForCal);
                } else if (bizCfgAlg.getPriKeyAlgType().equals(FieldAlgHelper.AlgType.SpecifyFields)) {
                    //取源数据字段
                    Map<String, BizFieldsForCal> oneBizDataField = updateBizDataFieldList.get(bizCfgAlg.getPriKeyAlgDesc());
                    if (oneBizDataField == null) {
                        oneBizDataField = new HashMap<>();
                        updateBizDataFieldList.put(bizCfgAlg.getPriKeyAlgDesc(), oneBizDataField);
                    }
                    BizFieldsForCal bizFieldsForCal = new BizFieldsForCal();
                    bizFieldsForCal.setFieldName(bizCfgField.getFieldName());
                    bizFieldsForCal.setFatherFieldName(bizCfgField.getFatherFieldName());
                    FieldAlgorithm fieldAlgorithm = FieldAlgHelper.get(bizCfgAlg.getAlgType(), bizCfgAlg.getAlgDesc());
                    bizFieldsForCal.setFieldAlgorithm(fieldAlgorithm);
                    oneBizDataField.put(bizCfgField.getFieldName(), bizFieldsForCal);
                }
            });
        }

        Converter keyConvert = new BizKeyGenerator();
        Converter valueConvert = new BizDataConverter();
        LocalDateTime ldt = LocalDateTime.now();

        //新增业务数据
        final String finalKeyFieldName = keyFieldName;
        createBizDataFieldList.entrySet().stream().forEach(bizDataBuildPlan -> {
            Map<String, BizFieldsForCal> keyGenList = new HashMap<>();
            BizFieldsForCal bizFieldsForCal = new BizFieldsForCal();
            bizFieldsForCal.setFieldAlgorithm(FieldAlgHelper.get(FieldAlgHelper.AlgType.UniqKeyGenerator, bizDataBuildPlan.getKey()));
            keyGenList.put(FieldAlgHelper.DEFAULT, bizFieldsForCal);
            //执行键值计算
            String bizKey = keyConvert.produce(srcJsonObj, keyGenList);
            //执行值计算
            String bizValue = valueConvert.produce(srcJsonObj, bizDataBuildPlan.getValue());

            if (StringUtils.isBlank(bizKey)) {
                log.error("执行键值不可为空, UniqKeyGenerator params:[{}]", bizDataBuildPlan.getKey());
                return;
            }

            //保存业务数据
            BizData bizData = new BizData();
            bizData.setUniqKey(bizKey);
            bizData.setUniqKeyName(finalKeyFieldName);
            bizData.setData(bizValue);
            bizData.setCreateTime(ldt);
            bizData.setModifyTime(ldt);
            bizData.setModelId(bizCfgModel.getModelId());
            bizDataService.save(bizData);

            JSONObject bizValueObj = JSONObject.parseObject(bizValue);
            //创建数据字典
            dictHandler.create(bizKey, bizValueObj, bizCfgModel);
            //创建查询索引
            indexHandler.create(bizData.getDataId(), bizValueObj, bizCfgModel);
        });

        //更新业务数据
        updateBizDataFieldList.entrySet().stream().forEach(stringMapEntry -> {
            Map<String, BizFieldsForCal> keyGenList = new HashMap<>();
            BizFieldsForCal bizFieldsForCal = new BizFieldsForCal();
            bizFieldsForCal.setFieldAlgorithm( FieldAlgHelper.get(FieldAlgHelper.AlgType.SpecifyFields, stringMapEntry.getKey()));
            keyGenList.put(FieldAlgHelper.DEFAULT, bizFieldsForCal);
            //执行键值计算
            String bizKey = keyConvert.produce(srcJsonObj, keyGenList);
            BizData bizData = bizDataService.getOneByUniqKey(bizKey);
            if (bizData != null) {
                //执行值计算
                String bizValue = valueConvert.produce(srcJsonObj, stringMapEntry.getValue());
                JSONObject newValueObj = JSONObject.parseObject(bizValue);
                JSONObject oldValueObj = JSONObject.parseObject(bizData.getData());
                oldValueObj.putAll(newValueObj); //更新的数据合并到原有数据上

                //更新业务数据
                bizData.setData(oldValueObj.toJSONString());
                bizData.setModifyTime(ldt);
                bizDataService.updateById(bizData);

                //更新索引数据
                indexHandler.update(bizData.getDataId(), oldValueObj, bizCfgModel);
            } else {
                log.error("无法获取可更新的数据，KEY：[{}]", bizKey);
            }
        });

    }

    @Override
    public boolean modelAuth(BizCfgModel bizCfgModel, User user) {
        if (bizCfgModel.getAuthType().contains("R") || bizCfgModel.getAuthType().contains("A")) {
            String[] authRoles = bizCfgModel.getAuthRoles().split(",");
            String[] userRoles = user.getRoleName().split(",");
            String[] authDepts = bizCfgModel.getAuthDepts().split(",");
            for (String authRole : authRoles) {
                for (String userRole : userRoles) {
                    if (authRole.equals(userRole)) {
                        if (bizCfgModel.getAuthType().contains("A")){
                            //判断部门
                            for (String authDept : authDepts) {
                                if (authDept.equals(user.getDeptId().toString())) {
                                    return true;
                                }
                            }
                        } else {
                            return true;
                        }
                    }
                }
            }
        }

        if (bizCfgModel.getAuthDepts().contains("D")) {
            String[] authDepts = bizCfgModel.getAuthDepts().split(",");
            for (String authDept : authDepts) {
                if (authDept.equals(user.getDeptId().toString())) {
                    return true;
                }
            }
        }


        return false;
    }
}
